package study.translation.grammar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class GrammarLoader
{
    public static final String GRAMMAR_EXT = ".obj";

    private File grammarFile;

    public GrammarLoader( String filename )
    {
        this( new File( filename ) );
    }

    public GrammarLoader( File file )
    {
        this.grammarFile = file;
    }

    public Grammar load() throws IOException, ParseException
    {
        if( !grammarFile.exists() )
        {
            throw new FileNotFoundException( grammarFile.getPath() );
        }
        Grammar grammar = loadFromSavedFile();
        if( null == grammar )
        {
            InputStream inputStream = null;
            try
            {
                inputStream = new FileInputStream( grammarFile );
                BNFParser parser = new BNFParser();
                grammar = parser.parse( inputStream );
            }
            finally
            {
                if( null != inputStream )
                {
                    inputStream.close();
                }
            }
            save( grammar );
        }
        return grammar;
    }

    private Grammar loadFromSavedFile()
    {
        Grammar grammar = null;
        File savedFile = new File( grammarFile.getPath() + GRAMMAR_EXT );
        if( savedFile.exists() )
        {

            try
            {
                FileInputStream fis = null;
                try
                {
                    fis = new FileInputStream( savedFile );
                    ObjectInputStream ois = new ObjectInputStream( fis );
                    if( grammarFile.lastModified() == ois.readLong() )
                    {
                        grammar = ( Grammar )ois.readObject();
                    }
                }
                finally
                {
                    if( null != fis )
                    {
                        fis.close();
                    }
                }
            }
            catch( Exception e )
            {
                // proceed
            }
        }
        return grammar;
    }

    private void save( Grammar grammar ) throws IOException
    {
        FileOutputStream fos = null;
        try
        {
            fos = new FileOutputStream( grammarFile.getPath() + GRAMMAR_EXT );
            ObjectOutputStream os = new ObjectOutputStream( fos );
            os.writeLong( grammarFile.lastModified() );
            os.writeObject( grammar );
        }
        finally
        {
            if( null != fos )
            {
                fos.close();
            }
        }
    }
}
